from drozer.modules import common, Module
from drozer.modules.common import loader

class Check(Module, common.PackageManager, loader.ClassLoader):

    name = "Open @jdwp-control and see which apps connect"
    description = "Open @jdwp-control and see which applications connect. This is an issue because then drozer can act as a debugger for the connected application. This could be used to invoke arbitrary code within the context of the debuggable application. See https://labs.mwrinfosecurity.com/blog/2011/07/07/debuggable-apps-in-android-market/ for more details."
    examples = """
    dz> run exploit.jdwp.check 
    [+] Opened @jdwp-control
    [*] Accepting connections

    [+] com.WithSecure.dz connected!
    [+] Received PID = 4931
    [+] This device is vulnerable!

    [+] com.WithSecure.dz connected!
    [+] Received PID = 4940
    [+] This device is vulnerable!
    """
    author = ["Tyrone (@mwrlabs)"]
    date = "2014-07-29"
    license = "BSD (3 clause)"
    path = ["exploit", "jdwp"]
    permissions = ["com.WithSecure.dz.permissions.GET_CONTEXT"]

    def execute(self, arguments):

        jdwp_class = self.loadClass("common/JdwpBroker.apk", "JdwpBroker")

        jdwp = self.new(jdwp_class)
        if jdwp.openJdwpControl() == "":
            self.stdout.write("[+] Opened @jdwp-control\n")
            self.stdout.write("[*] Accepting connections\n\n")

            while True:

                try:

                    uid = int(jdwp.acceptConnection())
                    package_name = str(self.packageManager().getNameForUid(uid))

                    self.stdout.write("[+] " + package_name + " connected!\n")

                    pid = str(jdwp.readPid())
                    if len(pid) == 4:
                        self.stdout.write("[+] Received PID = %s\n" % pid)
                        self.stdout.write("[+] This device is vulnerable!\n\n")
                    else:
                        self.stdout.write("[-] Did not receive PID...not vulnerable?\n\n")

                except KeyboardInterrupt:
                    self.stdout.write("[*] Closing @jdwp-control and exiting\n")
                    jdwp.closeJdwpControl()

        else:
            self.stdout.write("[-] @jdwp-control already in use\n")
            self.stdout.write("[*] Possible reasons for failure:\n")
            self.stdout.write("    # USB debugging is enabled\n")
            self.stdout.write("    # Port is still open from previous attempt\n")